#include <iostream>
#include "CGame.h"
#include <list>

#define IF(x) if(x)(x)

void CGame::Init()
{
	m_nmNetwork.Init( 7500 );

	m_timeCore.Reset();
	m_timeCore.Start();
	m_nFrames = 0;
	m_nLastClientCount = 0;
	cout << "[Game] Initialized.\n";
}

bool CGame::Run()
{
	//m_fTimeStep = (float)m_timeCore.GetElapsedTime();
	m_fTimeStep = 1.0f / 30.0f;
	m_timeCore.Reset();

	m_nFrames++;

	// Recieve Network Information
	char buff[1024];
	while( m_nmNetwork.peekBuffer() )
	{
		int hClient = m_nmNetwork.readBuffer( buff, 1024 );
		processMessage( buff + 4, hClient );
	}

	if( m_nLastClientCount != m_nmNetwork.ClientCount() )
	{
		m_nLastClientCount = m_nmNetwork.ClientCount();
		ModRobots();
	}

	m_nmNetwork.Update( m_fTimeStep );

	// Update Gamestate
	m_omObjects.Update( m_fTimeStep );

	// Send Updates to clients
	SendRobots();

	// Limit the tickrate
	while( m_timeCore.GetElapsedTime() < 1.0f / 30.0f ) {}

	// Displays FPS
	//static float time = 0.0f;
	//time += m_fTimeStep;
	//static int oldframes = 0;

	//if( time > 1.0f )
	//{
	//	int pastFrames = m_nFrames - oldframes;
	//	oldframes = m_nFrames;

	//	cout << "FPS: " << pastFrames << "\n";
	//	time = 0.0f;
	//}

	//cout << m_nDERP << "\n";

	return true;
}

void CGame::Shutdown()
{
	m_nmNetwork.Shutdown();
	m_omObjects.Clear();
}

void CGame::processMessage( char* _message, int _sender )
{
	switch( _message[0] )
	{
	case client_command:
		{
			switch( _message[1] )
			{
			case -1:
				IF( m_omObjects.GetRobot( m_umClientRobots[ _sender ] ) )->m_fPos.vX -= 1.0f;
				//cout << "[Game] Client[" << _sender << "] moved left.\n";
				break;
			case 0:
				break;
			case 1:
				IF( m_omObjects.GetRobot( m_umClientRobots[ _sender ] ) )->m_fPos.vX += 1.0f;
				//cout << "[Game] Client[" << _sender << "] moved right.\n";
				break;
			}

			break;
		}
	case client_getall:
		{
			break;
		}
	case client_getCount:
		{
			break;
		}
	}
}

void CGame::ModRobots()
{
	for( int i = 0; i < MAX_CLIENT_COUNT; ++i )
	{
		if( m_nmNetwork.m_ConnectedClients[ i ].active )
		{
			if( !m_umClientRobots.count( i ) )
			{
				unsigned int newRobHandle = m_omObjects.InsertRobot( float2( 200.0f, 200.0f ), float3( 1.0f, 1.0f, 1.0f ) );
				m_umClientRobots[ i ] = newRobHandle;
			}
		}
	}

	map< unsigned int, unsigned int>::iterator curr = m_umClientRobots.begin();

	list< int > toRemove;

	while( curr != m_umClientRobots.end() )
	{
		if( !m_nmNetwork.m_ConnectedClients[ (*curr).first ].active )
		{
			m_omObjects.KillRobot( (*curr).second );
			toRemove.push_back( (*curr).first );
		}

		curr++;
	}

	list< int >::iterator listCurr = toRemove.begin();

	while( listCurr != toRemove.end() )
	{
		m_umClientRobots.erase( (*listCurr) );
		listCurr++;
	}
}

void CGame::SendRobots()
{
	char buffer[ 64 ];
	memset( buffer, 0, 64 );
	char* bufPtr = buffer;

	list< sORobot* >::iterator currRob = m_omObjects.m_liRobots.begin();
	int id = 0;

	while( currRob != m_omObjects.m_liRobots.end() )
	{
		if( (*currRob ) )
		{
			*(int*)bufPtr = id;
			bufPtr += 4;
			*(float*)bufPtr = (*currRob)->m_fPos.vX;
			bufPtr += 4;
			*(float*)bufPtr = (*currRob)->m_fPos.vY;
			bufPtr += 4;
			*(float*)bufPtr = (*currRob)->m_fVel.vX;
			bufPtr += 4;
			*(float*)bufPtr = (*currRob)->m_fVel.vY;
			bufPtr += 4;
			*(float*)bufPtr = (*currRob)->m_fGunAngle;
			bufPtr += 4;
			*(float*)bufPtr = (*currRob)->m_fColor.cR;
			bufPtr += 4;
			*(float*)bufPtr = (*currRob)->m_fColor.cG;
			bufPtr += 4;
			*(float*)bufPtr = (*currRob)->m_fColor.cB;
			bufPtr += 4;

			m_nmNetwork.SendToAll( server_robotpos, buffer, 64 );
			memset( buffer, 0, 64 );
			bufPtr = buffer;
		}

		currRob++;
		id++;
	}

	//m_nmNetwork.SendToActiveClient( server_robotpos, nullptr, 0 );
}